home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1-sources / sources / kbd-patch / install.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-23  |  5.0 KB  |  195 lines  |  [TEXT/EMAC]

  1. /*
  2.  * Copyright (C) 1994 Marc Parmet.
  3.  * This file is part of the Macintosh port of GNU Emacs.
  4.  *
  5.  * GNU Emacs is distributed in the hope that it will be useful,
  6.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  8.  * GNU General Public License for more details.
  9.  */
  10.  
  11. /* This gives us NewRoutineDescriptor and NewFatRoutineDescriptor traps. */
  12. #define USESROUTINEDESCRIPTORS 1
  13.  
  14. #include <Types.h>
  15. #include <Memory.h>
  16. #include <MixedMode.h>
  17. #include <Traps.h>
  18. #include <Resources.h>
  19. #include <ToolUtils.h>
  20. #include <Processes.h>
  21. #include <FragLoad.h>
  22. #include <GestaltEqu.h>
  23. #include "emacs-version.h"
  24. #include "kbd-patch-data.h"
  25.  
  26. /* To make sure we use the powerPC versions of the patch. */
  27. #define TEST_POWERPC_CODE 0
  28.  
  29. int patch_contigous_long(Ptr,long);
  30. int patch_split_long(Ptr,long);
  31.  
  32. typedef    struct {
  33.     ProcPtr code;
  34.     Ptr toc;
  35. } transition_vector;
  36.  
  37. void
  38. install(void)
  39. {
  40.     int err;
  41.     THz old_zone;
  42.     char have_powerPC;
  43.     long response;
  44.     struct keyboard_patch_data *kbpd;
  45.     Handle KeyTrans_patch,gestalt_dispatch;
  46.     UniversalProcPtr KeyTrans_patch_upp,gestalt_dispatch_upp;
  47.     transition_vector *powerPC_KeyTrans_patch,*powerPC_gestalt_dispatch;
  48.  
  49.     /* Do nothing for an old system.  Emacs won't run on it. */
  50.     err = Gestalt(gestaltSystemVersion,&response);
  51.     if (err || LoWord(response) < 0x0700) return;
  52.  
  53.     /* We need some global data */
  54.     kbpd = (struct keyboard_patch_data *)NewPtrSys(sizeof(struct keyboard_patch_data));
  55.     kbpd->version = emacs_version_complete;
  56.     kbpd->original = NGetTrapAddress(_KeyTrans,ToolTrap);
  57.     kbpd->emacs_psn.lowLongOfPSN = kbpd->emacs_psn.highLongOfPSN = 0;
  58.     
  59.     /* Get the patch and gestalt code.  They must go into the system heap. */
  60.     KeyTrans_patch = GetResource('CODE',128);
  61.     if (KeyTrans_patch == 0L) return;
  62.     DetachResource(KeyTrans_patch);
  63.     if (ResError()) return;
  64.     HLock(KeyTrans_patch);
  65.     err = patch_contiguous_long(*KeyTrans_patch,(long)kbpd);
  66.     if (err) return;
  67.  
  68.     gestalt_dispatch = GetResource('CODE',129);
  69.     if (gestalt_dispatch == 0L) return;
  70.     DetachResource(gestalt_dispatch);
  71.     if (ResError()) return;
  72.     HLock(gestalt_dispatch);
  73.     err = patch_contiguous_long(*gestalt_dispatch,(long)kbpd);
  74.     if (err) return;
  75.  
  76.     /* If we have powerPC, install fat routine descriptors instead of ProcPtrs. */
  77.     err = Gestalt(gestaltSysArchitecture,&response);
  78.     have_powerPC = !err && (response == gestaltPowerPC);
  79.     if (have_powerPC) {
  80.         err = load_powerPC_code(&powerPC_KeyTrans_patch,&powerPC_gestalt_dispatch);
  81.         if (err) have_powerPC = 0;
  82.         err = patch_split_long((Ptr)powerPC_KeyTrans_patch->code,(long)kbpd);
  83.         if (err) have_powerPC = 0;
  84.         err = patch_split_long((Ptr)powerPC_gestalt_dispatch->code,(long)kbpd);
  85.         if (err) have_powerPC = 0;
  86.     }
  87.  
  88.     /* Create the UPP's in the system heap. */
  89.  
  90.     if (have_powerPC) {
  91.         old_zone = GetZone();
  92.         SetZone(SystemZone());
  93.  
  94. #if TEST_POWERPC_CODE
  95.         KeyTrans_patch_upp =
  96.             NewRoutineDescriptor((ProcPtr)powerPC_KeyTrans_patch,
  97.                                  uppKeyTransProcInfo,
  98.                                  kPowerPCISA);
  99.         gestalt_dispatch_upp =
  100.             NewRoutineDescriptor((ProcPtr)powerPC_gestalt_dispatch,
  101.                                  uppSelectorFunctionProcInfo,
  102.                                  kPowerPCISA);
  103. #else
  104.         KeyTrans_patch_upp =
  105.             NewFatRoutineDescriptor((ProcPtr)*KeyTrans_patch,
  106.                                     (ProcPtr)powerPC_KeyTrans_patch,
  107.                                     uppKeyTransProcInfo);
  108.         gestalt_dispatch_upp =
  109.             NewFatRoutineDescriptor((ProcPtr)*gestalt_dispatch,
  110.                                     (ProcPtr)powerPC_gestalt_dispatch,
  111.                                     uppSelectorFunctionProcInfo);
  112. #endif
  113.  
  114.         SetZone(old_zone);
  115.     }
  116.     else {
  117.         KeyTrans_patch_upp = (UniversalProcPtr)*KeyTrans_patch;
  118.         gestalt_dispatch_upp = (UniversalProcPtr)*gestalt_dispatch;
  119.     }
  120.     
  121.     /* Commit the patch. */
  122.     NSetTrapAddress(KeyTrans_patch_upp,_KeyTrans,ToolTrap);
  123.  
  124.     /* Install a hook so that Emacs when launched can install its data for the patch. */
  125.     err = NewGestalt('EMAc',gestalt_dispatch_upp);
  126. }
  127.  
  128. int
  129. patch_contiguous_long(Ptr h,long replacement)
  130. {
  131.     long i;
  132.     short *q = (short *)h;
  133.  
  134.     for (i = 0; i<20; ++i) {
  135.         if (*(long *)&q[i] == PATCH_MAGIC) {
  136.             *(long *)&q[i] = replacement;
  137.             return 0;
  138.         }
  139.     }
  140.     
  141.     return -1;
  142. }
  143.  
  144. int
  145. patch_split_long(Ptr h,long replacement)
  146. {
  147.     long i;
  148.     short *q = (short *)h;
  149.     
  150.     for (i = 0; i<20; ++i) {
  151.         if (q[i] == HiWord(PATCH_MAGIC) && q[i+2] == LoWord(PATCH_MAGIC)) {
  152.             q[i] = HiWord(replacement);
  153.             q[i+2] = LoWord(replacement);
  154.             return 0;
  155.         }
  156.     }
  157.     
  158.     return -1;
  159. }
  160.  
  161. int
  162. load_powerPC_code(transition_vector **text_code,transition_vector **gestalt_code)
  163. {
  164.     int err;
  165.     long size;
  166.     Ptr mainAddr;
  167.     SymClass symClass;
  168.     Handle powerPC_code;
  169.     ConnectionID connID;
  170.     unsigned char errName[256],s[256];
  171.  
  172.     powerPC_code = GetResource('CODE',130);
  173.     if (powerPC_code == 0L) return -1;
  174.     DetachResource(powerPC_code);
  175.     if (ResError()) return -1;
  176.     size = GetHandleSize(powerPC_code);
  177.     if (MemError()) return -1;
  178.     HLock(powerPC_code);
  179.  
  180.     GetIndString(s,128,1);
  181.     err = GetMemFragment(*powerPC_code,size,s,
  182.                          kLoadLib,&connID,&mainAddr,errName);
  183.     if (err) return -1;
  184.  
  185.     GetIndString(s,128,2);
  186.     err = FindSymbol(connID,s,(Ptr *)text_code,&symClass);
  187.     if (err) return -1;
  188.  
  189.     GetIndString(s,128,3);
  190.     err = FindSymbol(connID,s,(Ptr *)gestalt_code,&symClass);
  191.     if (err) return -1;
  192.  
  193.     return 0;
  194. }
  195.